home *** CD-ROM | disk | FTP | other *** search
- /*
- * elog.c --
- * error logger
- */
- #include <stdio.h>
- #include <strings.h>
- #include <sys/file.h>
- #include <sys/types.h>
- #include <varargs.h>
-
- #include "tmp/postgres.h"
- #include "utils/log.h"
- #include "installinfo.h"
-
- RcsId("$Header: /private/postgres/src/utils/error/RCS/elog.c,v 1.23 1992/08/07 00:43:22 mao Exp $");
-
-
- int Debug_file = -1;
- int Err_file = -1;
- int ElogDebugIndentLevel;
-
- /*
- * If the parser has detected an empty query from the front end, then
- * there is a chance that the front end has shut down. If this happens,
- * and we try to send a bunch of elog messages over our connection to
- * the front end, and we're running Ultrix 3.x, then fflush on the
- * connection socket can cause us to die without a core dump. Cool, yes?
- * The global below is set in PostgresMain and used here to work around
- * this operating system bug.
- */
-
- void
- EnableELog(enable)
- int enable;
- {
- static int numEnabled;
- static int fault;
-
- Assert(fault == 0);
-
- if (!enable && --numEnabled)
- return;
- if (enable && numEnabled++)
- return;
-
- ++fault;
- if (enable) {
- /* XXX */
- ;
- } else {
- /* XXX */
- ;
- }
- --fault;
- }
-
-
- /*VARARGS2*/
- void
- elog(va_alist)
- va_dcl
- {
- va_list ap;
- register int lev;
- char *fmt;
- char buf[ELOG_MAXLEN], line[ELOG_MAXLEN];
- register char *bp, *cp;
- extern int errno, sys_nerr;
- extern char *sys_errlist[], *ctime(), *sprintf();
- #ifndef PG_STANDALONE
- extern FILE *Pfout;
- #endif /* !PG_STANDALONE */
- time_t tim, time();
- int len;
- int i = 0;
-
- va_start(ap);
- lev = va_arg(ap, int);
- fmt = va_arg(ap, char *);
- if (lev == DEBUG && Debug_file < 0) {
- return;
- }
- switch (lev) {
- case NOIND:
- i = ElogDebugIndentLevel-1;
- if (i < 0) i = 0;
- if (i > 30) i = i%30;
- cp = "DEBUG:";
- break;
- case DEBUG:
- i = ElogDebugIndentLevel;
- if (i < 0) i = 0;
- if (i > 30) i = i%30;
- cp = "DEBUG:";
- break;
- case NOTICE:
- cp = "NOTICE:";
- break;
- case WARN:
- cp = "WARN:";
- break;
- default:
- sprintf(line, "FATAL %d:", lev);
- cp = line;
- }
- time(&tim);
- strcat(strcpy(buf, cp), ctime(&tim)+4);
- bp = buf+strlen(buf)-6;
- *bp++ = ':';
- while (i-- >0) *bp++ = ' ';
- for (cp = fmt; *cp; cp++)
- if (*cp == '%' && *(cp+1) == 'm') {
- if (errno < sys_nerr && errno >= 0)
- strcpy(bp, sys_errlist[errno]);
- else
- sprintf(bp, "error %d", errno);
- bp += strlen(bp);
- cp++;
- } else
- *bp++ = *cp;
- *bp = '\0';
- vsprintf(line, buf, ap);
- va_end(ap);
- len = strlen(strcat(line, "\n"));
- if (Debug_file > -1)
- write(Debug_file, line, len);
- if (lev == DEBUG || lev == NOIND)
- return;
-
- /*
- * If there's an error log file other than our channel to the
- * front-end program, write to it first. This is important
- * because there's a bug in the socket code on ultrix. If the
- * front end has gone away (so the channel to it has been closed
- * at the other end), then writing here can cause this backend
- * to exit without warning -- that is, write() does an exit().
- * In this case, our only hope of finding out what's going on
- * is if Err_file was set to some disk log. This is a major pain.
- */
-
- if (Err_file > -1 && Debug_file != Err_file) {
- if (write(Err_file, line, len) < 0) {
- write(open("/dev/console", O_WRONLY, 0666), line, len);
- fflush(stdout);
- fflush(stderr);
- exitpg(lev);
- }
- #ifndef linux
- /*
- * Sorry, Linux does not seem to have fsync() (yet).
- */
- fsync(Err_file);
- #endif
- }
-
- #ifndef PG_STANDALONE
- /* Send IPC message to the front-end program */
- if (Pfout != NULL && lev > DEBUG) {
- /* notices are not exactly errors, handle it differently */
- if (lev == NOTICE)
- pq_putnchar("N", 1);
- else
- pq_putnchar("E", 1);
- pq_putint(-101, 4); /* should be query id */
- pq_putstr(line);
- pq_flush();
- }
- #endif /* !PG_STANDALONE */
-
- if (lev == WARN) {
- ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
- kill(getpid(), 1); /* abort to traffic cop */
- }
-
- if (lev == FATAL) {
- /*
- * Assume that if we have detected the failure we can
- * exit with a normal exit status. This will prevent
- * the postmaster from cleaning up when it's not needed.
- */
- fflush(stdout);
- fflush(stderr);
- ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
- ProcReleaseLocks(); /* get rid of real locks we hold */
- exitpg(0);
- }
-
- if (lev > FATAL) {
- fflush(stdout);
- fflush(stderr);
- exitpg(lev);
- }
- }
-
-
- /*
- * GetDataHome
- *
- * Extract the installation home directory from the environment.
- */
-
- extern char *PostgresHomes[];
- extern int NStriping;
- extern int StripingMode;
-
- char *
- GetDataHome()
- {
- char *home;
- char *p, *p1;
- int i;
- extern char *getenv();
-
- home = getenv("POSTGRESHOME");
- if (!StringIsValid(home)) {
- home = getenv("POSTHOME");
- }
- if (!StringIsValid(home)) {
- home = DATAHOME;
- }
- if (!StringIsValid(home)) return NULL;
- p = home;
- i = 0;
- while ((p1 = index(p, ':')) != NULL) {
- *p1 = '\0';
- PostgresHomes[i++] = p;
- p = p1 + 1;
- }
- if (*p >= '0' && *p <= '9') {
- /* specify raid level */
- StripingMode = atoi(p);
- }
- else {
- PostgresHomes[i++] = p;
- }
- NStriping = i;
- if (StripingMode == 1) {
- if (NStriping % 2 != 0)
- elog(FATAL,"RAID Level 1 has to have an even number of disks.");
- NStriping /= 2;
- }
- else if (StripingMode < 0 || StripingMode > 5)
- elog(FATAL, "We only have RAID Level 0 -- 5.");
- else if (StripingMode > 1 && StripingMode < 5)
- elog(FATAL, "only RAID 0, 1 and 5 are supported.");
- return(home);
- }
-
-
- ErrorFileOpen()
- {
- int fd;
- char buffer[MAXPGPATH];
- extern char *GetDataHome();
-
- fd = fileno(stderr);
-
- if (fcntl(fd, F_GETFD, 0) < 0) {
- sprintf(buffer, "%s/data/pg.errors\0", GetDataHome());
- fd = open(buffer, O_CREAT|O_APPEND|O_WRONLY, 0666);
- if (fd < 0)
- elog(FATAL, "ErrorFileOpen: open(%s) failed", buffer);
- }
-
- return(fd);
- }
-
-
- DebugFileOpen()
- {
- int fd;
- char buffer[MAXPGPATH];
- extern char *GetDataHome();
-
- fd = fileno(stderr);
- if (fcntl(fd, F_GETFD, 0) < 0) {
- sprintf(buffer, "%s/data/pg.debug\0", GetDataHome());
- /*
- elog(NOTICE, "DebugFileOpen: opening %s", buffer);
- */
- fd = open(buffer, O_CREAT|O_APPEND|O_WRONLY, 0666);
- if (fd < 0)
- elog(FATAL, "DebugFileOpen: open(%s) failed", buffer);
- }
- /*
- elog(NOTICE, "DebugFileOpen: opened %s, fd=%d", buffer, fd);
- */
- return(fd);
- }
-